﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MoneyWentWhere.DataModel.Collections
{
    class SparseTable<T> : ITable<T>
    {
        // Indexed by rowIndex, colIndex
        Dictionary<int, Dictionary<int, T>> _table = new Dictionary<int, Dictionary<int, T>>();

        int _rowCount = 0;
        int _columnCount = 0;

        public T this[int rowIndex, int colIndex]
        {
            get
            {
                if (rowIndex < 0) { throw new IndexOutOfRangeException("rowIndex"); }
                if (colIndex < 0) { throw new IndexOutOfRangeException("colIndex"); }

                Dictionary<int, T> row;
                if (!_table.TryGetValue(rowIndex, out row))
                {
                    return default(T);
                }

                T value;
                if (!row.TryGetValue(colIndex, out value))
                {
                    return default(T);
                }

                return value;
            }
            set
            {
                if (rowIndex < 0) { throw new IndexOutOfRangeException("rowIndex"); }
                if (colIndex < 0) { throw new IndexOutOfRangeException("colIndex"); }

                Dictionary<int, T> row;
                if (!_table.TryGetValue(rowIndex, out row))
                {
                    row = new Dictionary<int, T>();
                    _table.Add(rowIndex, row);

                    if (rowIndex + 1 > _rowCount) { _rowCount = rowIndex + 1; }
                }

                // TODO: delete cell (and row if it becomes empty) when value == default(T)

                if (!row.ContainsKey(colIndex))
                {
                    row.Add(colIndex, value);
                }
                else 
                {
                    row[colIndex] = value;
                }

                if (colIndex + 1 > _columnCount) { _columnCount = colIndex + 1; }
            }
        }

        public int RowCount { get { return _rowCount; } }
        public int ColumnCount { get { return _columnCount; } }

        public override string ToString()
        {
            // Output all elements stored in the sparse table.
            // Each row headed by the index. No headers for cols for now.

            StringBuilder sb = new StringBuilder();
            foreach(int rowNum in _table.Keys)
            {
                Dictionary<int, T> cols = _table[rowNum];
                sb.Append(rowNum + ",");
                foreach(int colNum in cols.Keys)
                {
                    sb.Append(cols[colNum].ToCsvEscapedString());
                    sb.Append(",");
                }
                sb.AppendLine();
            }
            return sb.ToString();
        }
    }
}
